#pragma once
#include <iostream>
#include <list>
#include <functional>
using namespace std;
#define FPDelegate

template<typename S, typename E>
class EventHandler
{
public:
#ifdef FPDelegate
	typedef bool(S::*FP)(S, E);
	void operator +=(FP fp)
	{
		lstFuncs.push_back(fp);
	}
	void operator +=(function<bool(S, E)> func)
	{
		//auto it = std::find(lstFuncObj.begin(), lstFuncObj.end(), func);
		//if (it != lstFuncObj.end())
		lstFuncObj.push_back(func);
	}
	std::list<FP> lstFuncs;
#endif // FUNCPOINTER

	void Invoke(S s, E e)
	{
#ifdef FPDelegate
		for (auto it = lstFuncs.begin(); it != lstFuncs.end(); it++)
		{
			//auto f =  std::bind(*it, s);
			(s.**it)(s, e);
		}
#endif
		for (auto it = lstFuncObj.begin(); it != lstFuncObj.end(); it++)
		{
			(*it)(s, e);
		}
	}
	std::list<function<bool(S, E)>> lstFuncObj;
};

class EventArgs
{
public:
	std::string arg1;
	int t;
	int y;
};

#define DELEGATE(t) std::bind(&t, this, _1, _2);

class Sender
{
public:
	std::string name;
	EventHandler<Sender, EventArgs> eh;

	Sender()
	{
		//eh += &Sender::EventHandle;
		using namespace  std::placeholders;
		//function<bool(Sender, EventArgs)> se = std::bind(&Sender::EventHandle, this, _1, _2);
		//eh += std::bind(&Sender::EventHandle, this, _1, _2);
		eh += DELEGATE(Sender::EventHandle);
		name = "1232131";
		EventArgs arg;
		arg.arg1 = "arg1";
		arg.t = 22;
		arg.y = 13;
		eh.Invoke(*this, arg);
	}
	bool EventHandle(Sender s, EventArgs ea)
	{
		cout << "event handler s:" << s.name.data() << " EventArgs:" << ea.arg1.data() << "," << ea.t << "," << ea.y;
		return false;
	}
};



//int main()
//{
//	Sender s;
//	getchar();
//	std::cout << "\n";
//}
//
